package com.uoko.fileupload.util;

import com.uoko.fileupload.config.FileUploadProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * <p>
 * 文件上传工具类
 * </p>
 *
 * @author shaohua
 * Email shaohua@uoko.com
 * created by 2018/6/8
 */
@Component
public class FileSave {


    @Autowired
    private static FileUploadProperties fileUploadProperties;

    private static final File UPLOAD_DIRECTORY = new File(getRealPath());

    /**
     * 文件保存
     *
     * @param savePath
     * @param fileFullName
     * @param file
     * @return
     * @throws Exception
     */
    public static boolean saveFile(@NotNull final String savePath,
                                   @NotNull final String fileFullName,
                                   @NotNull final MultipartFile file)
            throws Exception {
        byte[] data = readInputStream(file.getInputStream());
        //new 一个文件来存放保存的文件，默认是文件的根目录
        File uploadFile = new File(savePath + fileFullName);
        //判断存放文件的文件是否存在，不存在创建
        File fileDirectory = new File(savePath);
        synchronized (UPLOAD_DIRECTORY) {
            if (UPLOAD_DIRECTORY.exists()) {
                if (!UPLOAD_DIRECTORY.mkdir()) {
                    throw new Exception("保存文件的父文件夹创建失败！路径为：" + savePath);
                }
            }
            if (!fileDirectory.exists()) {
                if (!fileDirectory.mkdir()) {
                    throw new Exception("文件夹创建失败！路径为：" + savePath);
                }
            }
        }
        //创建输出流
        try (FileOutputStream outputStream = new FileOutputStream(uploadFile)) {
            outputStream.write(data);
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return uploadFile.exists();
    }

    /**
     * 将输入流转换成byte字符串
     *
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static byte[] readInputStream(InputStream inputStream) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        //创建一个buffer字符串
        byte[] buffer = new byte[1024];
        //每次读取的字符串的长度，如果为-1，代表全部读取完毕
        int len;
        //使用一个输入流成buffer里把数据读取出来
        while ((len = inputStream.read(buffer)) != -1) {
            //用输出流网buffer里写入数据，中间参数代表从哪个位置开始读取，len代表读取长度
            outputStream.write(buffer, 0, len);
        }
        //关闭输入流
        inputStream.close();
        //把outStream里的数据写入内存
        return outputStream.toByteArray();
    }


    /**
     * 获取文件的路径绝对路径
     *
     * @return
     */
    public static String getRealPath() {
        return fileUploadProperties.getFileDirectory();
    }

    /**
     * 通过File 获取文件路径
     *
     * @param filePath 文件路径
     * @return
     */
    public static File getFileByPath(String filePath) throws IOException {
        Path path = Paths.get(getRealPath() + filePath);
        if (Files.exists(path)) {
            return new File(path.toUri());
        }
        return null;
    }


    /**
     * 压缩文件
     *
     * @param srcFileList
     * @param zipFile
     * @throws IOException
     */
    public static void zipFiles(List<File> srcFileList, java.io.File zipFile) throws IOException {
        byte[] buf = new byte[1024];
        //ZipOutputStream类：完成文件或文件夹的压缩
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));

        for (java.io.File aSrcFileList : srcFileList) {
            FileInputStream in = new FileInputStream(aSrcFileList);
            out.putNextEntry(new ZipEntry(aSrcFileList.getName()));
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            out.closeEntry();
            in.close();
        }
        out.close();
    }

}
